与遗留数据库整合
Django的数据库层从Python代码生成SQL schemas—但是对于遗留数据库,你已经拥有SQL schemas。 这种情况,你需要为已经存在的数据表创建model。为此,Django自带了一个可以通过读取您的数据表结构来生成model的工具。该辅助工具称为inspectdb,你可以通过执行manage.py inspectdb
来调用它.
使用 inspectdb
inspectdb工具自省你配置文件指向的数据库,针对每一个表生成一个Django模型,然后将这些Python模型的代码显示在系统的标准输出里面。
下面是一个从头开始的针对一个典型的遗留数据库的整合过程。两个前提条件是安装了Django和一个传统数据库。
- 通过运行
django-admin.py startproject mysite
(这里mysite
是你的项目的名字)建立一个Django项目。 好的,那我们在这个例子中就用这个mysite
作为项目的名字。 - 编辑项目中的配置文件,
mysite/settings.py
,告诉Django你的数据库连接参数和数据库名。具体的说,要提供DATABASE_NAME
,DATABASE_ENGINE
,DATABASE_USER
,DATABASE_PASSWORD
,DATABASE_HOST
和DATABASE_PORT
这些配置信息。 (请注意其中的一些设置是可选的。更多信息参见第5章) - 通过运行
python mysite/manage.py startapp myapp
(这里myapp
是你的应用的名字)创建一个Django应用。 这里我们使用myapp
做为应用名。 运行命令
python mysite/manage.py inspectdb
。这将检查DATABASE_NAME
数据库中所有的表并打印出为每张表生成的模型类。 看一看输出结果以了解inspectdb
能做些什么。将标准shell的输出重定向,保存输出到你的应用的
models.py
文件里:python mysite/manage.py inspectdb > mysite/myapp/models.py
编辑 mysite/myapp/models.py 文件以清理生成的 models 并且做一些必要的自定义。 针对这个,下一个节有些好的建议。
清理生成的Models
如你可能会预料到的,数据库自省不是完美的,你需要对产生的模型代码做些许清理。 这里提醒一点关于处理生成 models 的要点:
- 数据库的每一个表都会被转化为一个model类 (也就是说,数据库的表和model 类之间是一对一的映射)。 这意味着你需要为多对多连接的表,重构其models 为
ManyToManyField
的对象。 所生成的每一个model中的每个字段都拥有自己的属性,包括
id
主键字段。 但是,请注意,如果某个model没有主键的话,那么Django会自动为其增加一个id
主键字段。 这样一来,你也许希望移除这样的代码行。id = models.IntegerField(primary_key=True)
这样做并不是仅仅因为这些行是冗余的,而且如果当你的应用需要向这些表中增加新记录时,这些行会导致某些问题。
- 每一个字段类型,如
CharField
、DateField
,是通过查找数据库列类型如VARCHAR
,DATE
来确定的。如果inspectdb
无法把某个数据库字段映射到model字段上,它会使用TextField
字段进行代替,并且会在所生成model字段后面加入Python注释“该字段类型是猜的”。对这要当心,如果必要的话,更改字段类型。 - 如果你的数据库中的某个字段在Django中找不到合适的对应物,你可以放心的略过它。Django模型层不要求必须导入你数据库表中的每个列。
如果数据库中某个列的名字是Python的保留字(比如
pass
、class
或者for
等),inspectdb
会在每个属性名后附加上_field
,并将db_column
属性设置为真实的字段名(也就是pass
,class
或者for
等)。例如,某张表中包含一个
INT
类型的列,其列名为for
,那么所生成的model将会包含如下所示的一个字段:for_field = models.IntegerField(db_column='for')
inspectdb
会在该字段后加注 “字段重命名,因为它是一个Python保留字” 。如果数据库中某张表引用了其他表(正如大多数数据库系统所做的那样),你需要适当的修改所生成model的顺序,以使得这种引用能够正确映射。 例如,model
Book
拥有一个针对于modelAuthor
的外键,那么后者应该先于前者被定义。如果你想创建一个指向尚未定义的model的关系,那么可以使用包含model名的字符串,而不是model对象本身。对于PostgreSQL,MySQL和SQLite数据库系统,
inspectdb
能够自动检测出主键关系。也就是说,它会在合适的位置插入primary_key=True
。 而对于其他数据库系统,你必须为每一个model中至少一个字段插入这样的语句,因为Django的model要求必须拥有一个primary_key=True
的字段。外键检测仅对PostgreSQL,还有MySQL表中的某些特定类型生效。 至于其他数据库,外键字段将在假定其为INT列的情况下被自动生成为IntegerField。
{$ activeFileHint $}